package org.csu.springjpetstore.controller;

import org.csu.springjpetstore.domain.Account;
import org.csu.springjpetstore.domain.Cart;
import org.csu.springjpetstore.service.AccountService1;
import org.csu.springjpetstore.service.CartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Random;


@Controller
@RequestMapping(value = "/account")
@SessionAttributes(value = {"code1", "msg", "loginUser", "loginUser", "cart"})
public class AccountController {
    @Autowired
    AccountService1 accountService1;
    @Autowired
    CartService cartService;


    /**
     * 是否进行验证码验证 为false登录不需要验证码
     */
    public static boolean isVerify = false;

    @RequestMapping(value = "/loginForm", method = RequestMethod.GET)
    public String loginForm() {
        return "account/SignOnForm";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@RequestParam("username") String username, @RequestParam("password") String password,
                        @RequestParam("code") String code, Model model,
                        @SessionAttribute(name = "code1") String code1,
                        @Autowired HttpServletRequest request) {
        try {
            request.setCharacterEncoding("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //是否需要验证码验证
        if (isVerify) {
            //验证验证码是否正确
            //验证码不区分大小写 (equalsIgnoreCase)
            if (!code.equalsIgnoreCase(code1)) {
                request.setAttribute("msg", "验证码错误");
                return "account/SignOnForm";
            }
        }
        //验证账号与密码

        //MD5加密算法
        String md5Pas = getMD5String(password);
        Account loginUser = accountService1.login(username, md5Pas);

        if (loginUser == null) {
            request.setAttribute("msg", "用户名或密码错误");
            return "account/SignOnForm";
        } else {
            //登录成功
            Cart cart;
            cart = cartService.getCartByName(loginUser.getUsername());
            System.out.println(cart.getCartItemList());
            //个人信息读取到session中
            model.addAttribute("loginUser", loginUser);
            model.addAttribute("cart", cart);
            return "catalog/Main";
        }
    }

    @RequestMapping(value = "/modifyForm", method = RequestMethod.POST)
    public String modifyForm() {

        return "account/EditAccountForm";
    }

    @RequestMapping(value = "/signOut", method = RequestMethod.GET)
    public String signOut(Model model) {
        model.addAttribute("loginUser", new Account());
        return "catalog/Main";
    }


    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String register(@RequestParam("username") String username,
                           @RequestParam("password") String password,
                           @RequestParam("password2") String password2,
                           Model model, @Autowired HttpServletRequest request) {

//        AccountService service = new AccountServiceImpl();//todo
        if (username == null || password == null || username.equals("") || password.equals("")) {

            request.setAttribute("msg", "用户名或密码为空，请重新输入");
            return "account/NewAccountForm";
        }
        if (!password.equals(password2)) {
            request.setAttribute("msg", "两次密码不一致，请重新输入");
            return "account/NewAccountForm";
        }

        Account tmpAccount = new Account();

        tmpAccount.setAddress1(request.getParameter("address1"));
        tmpAccount.setAddress2(request.getParameter("address2"));
        tmpAccount.setCity(request.getParameter("city"));
        tmpAccount.setUsername(request.getParameter("username"));
        //加密算法
        String md5password = getMD5String(request.getParameter("password"));
        tmpAccount.setPassword(md5password);
        tmpAccount.setPhone(request.getParameter("phone"));
        tmpAccount.setLanguagePreference(request.getParameter("languagePreference"));
        tmpAccount.setBannerOption(request.getParameter("myBanner") == ("myBanner"));
        tmpAccount.setCountry(request.getParameter("county"));
        tmpAccount.setEmail(request.getParameter("email"));
        tmpAccount.setFavouriteCategoryId(request.getParameter("categoryPreference"));
        tmpAccount.setFirstName(request.getParameter("firstName"));
        tmpAccount.setLastName(request.getParameter("lastName"));
        tmpAccount.setListOption(request.getParameter("myList") == ("myList"));
        tmpAccount.setState(request.getParameter("state"));
        tmpAccount.setStatus(request.getParameter("status"));
        tmpAccount.setZip(request.getParameter("zip"));
        int count = accountService1.register(tmpAccount);

        if (count == -1) {
            request.setAttribute("msg", "该用户名已注册，请重新输入用户名");
            return "account/NewAccountForm";
        }
        if (count == 0) {
            request.setAttribute("msg", "网络貌似出问题了，请重试");
            return "account/NewAccountForm";
        }
        request.setAttribute("msg", "注册成功，请登录");
        return "account/SignOnForm";
    }

    @RequestMapping(value = "/registerForm", method = RequestMethod.GET)
    public String registerForm(@Autowired HttpServletResponse response) {
        response.setContentType("application/json;charset=utf-8");
        return "account/NewAccountForm";
    }

    @RequestMapping(value = "/editAccount", method = RequestMethod.POST)
    public String editAccount(@Autowired HttpServletRequest request,
                              @SessionAttribute(name = "loginUser") Account loginUser,
                              Model model) {
        //由于在修改用户信息时,默认用户不能修改自己的用户名,因此用request.getParameter("username")始终获取不到
        if (loginUser.getUsername() == null || request.getParameter("password") == null ||
                loginUser.getUsername().equals("") || request.getParameter("password").equals("")) {
            request.setAttribute("msg", "用户名或密码为空，请重新输入");
            return "account/EditAccountForm";
        } else if (!request.getParameter("password").equals(request.getParameter("repeatedPassword"))) {
            request.setAttribute("msg", "两次密码不一致，请重新输入");
            return "account/EditAccountForm";
        } else {
            Account user = new Account();
            user.setAddress1(request.getParameter("address1"));
            user.setAddress2(request.getParameter("address2"));
            user.setCity(request.getParameter("city"));
            user.setUsername(loginUser.getUsername());
            user.setPassword(request.getParameter("password"));
            user.setPhone(request.getParameter("phone"));
            user.setLanguagePreference(request.getParameter("languagePreference"));
            user.setBannerOption(request.getParameter("myBanner") == "myList");
            user.setCountry(request.getParameter("county"));
            user.setEmail(request.getParameter("email"));
            user.setFavouriteCategoryId(request.getParameter("categoryPreference"));
            user.setFirstName(request.getParameter("firstName"));
            user.setLastName(request.getParameter("lastName"));
            user.setListOption(request.getParameter("myList") == "myList");
            user.setState(request.getParameter("state"));
            user.setStatus(request.getParameter("status"));
            user.setZip(request.getParameter("zip"));

            int count = accountService1.editAccountIncludeUsername(user, loginUser.getUsername());
            if (count == -1) {
                request.setAttribute("msg", "该用户名已注册，请重新输入用户名");
                return "account/NewAccountForm";

            }
            if (count == 0) {
                request.setAttribute("msg", "网络貌似出问题了，请重试");
                return "account/NewAccountForm";
            }
            model.addAttribute("loginUser", user);
            return "catalog/Main";
        }
    }


    @RequestMapping(value = "/myAccountForm", method = RequestMethod.GET)
    public String myAccountForm(Account loginUser, Model model,
                                @Autowired HttpServletRequest request) {

        if (loginUser == null) {
            request.setAttribute("msg", "请先登录");
            return "account/SignOnForm";
        }
        return "account/MyAccountFields";
    }

    @RequestMapping(value = "/usernameIsExist", method = RequestMethod.GET)
    public String usernameIsExistServlet(@RequestParam(name = "username") String username,
                                         @Autowired HttpServletResponse response) {//TODO 不确定运行情况是什么样的
        response.setContentType("text/plain");
        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (username == null || username.equals("")) {
            out.print("Empty");
            out.flush();
            out.close();
        } else {
            if (accountService1.getAccount(username) != null) {
                out.print("Exist");
            } else {
                out.print("Not Exist");
            }
            out.flush();
            out.close();
        }
        return null;
    }


    @RequestMapping(value = "/code", method = RequestMethod.GET)
    public String getCodeImage(@Autowired HttpServletResponse response, Model model, @Autowired HttpServletRequest request) {
        //创建空白图片
        BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB);
        //获取图片画笔
        Graphics g = image.getGraphics();
        Random r = new Random();
        //设置画笔颜色
        g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
        //绘制矩形背景
        g.fillRect(0, 0, 100, 30);
        //绘制20条干扰线
        for (int i = 0; i < 20; i++) {
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
            g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30));

        }
        //设置画笔颜色
        g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
        //调用方法，获取长度为4的随机字符串

        String str1 = getRanString(4);
        //将生成的验证码存在session里
        model.addAttribute("code1", str1);
        g.setFont(new Font(null, Font.BOLD + Font.ITALIC, 24));
        g.drawString(str1, 15, 25);


        //发送图片到客户端
        response.setContentType("image/jpeg");
        try {
            /*
            https://blog.csdn.net/hanchao5272/article/details/80540751
            在Response响应(response.getOutputStream())之后，才创建Session(request.getSession())。
            而此时已经找不到Session ID，所以会报错。
            下面这行 request.getSession(true); 一定要加
            */
            request.getSession(true);
            OutputStream out = response.getOutputStream();
            //将图片输入到页面展示
            ImageIO.write(image, "jpeg", out);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    private String getRanString(int size) {
        String str = "ABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789";
        String number = "";
        Random r = new Random();
        for (int i = 0; i < size; i++) {
            char c = str.charAt(r.nextInt(str.length()));
            number = number + c;
        }
        return number;
    }

    //MD5加密算法
    public static String getMD5String(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值，返回值为8位字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            //一个byte是八位二进制，也就是2位十六进制字符（2的8次方等于16的2次方）
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

